package cn.edu.sgu.www.mhxysy.service.chongwu.impl;

import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.consts.CustomDirectories;
import cn.edu.sgu.www.mhxysy.dto.chongwu.ChongwuNeidanCategoryDTO;
import cn.edu.sgu.www.mhxysy.entity.chongwu.ChongwuCategory;
import cn.edu.sgu.www.mhxysy.entity.chongwu.ChongwuNeidanCategory;
import cn.edu.sgu.www.mhxysy.enums.NeidanTypes;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.chongwu.ChongwuCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.chongwu.ChongwuNeidanCategoryMapper;
import cn.edu.sgu.www.mhxysy.pager.chongwu.ChongwuNeidanCategoryPager;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.chongwu.ChongwuNeidanCategoryService;
import cn.edu.sgu.www.mhxysy.util.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class ChongwuNeidanCategoryServiceImpl implements ChongwuNeidanCategoryService {

	private final UploadUtils uploadUtils;
	private final ImageUpdater imageUpdater;
	private final ChongwuCategoryMapper chongwuCategoryMapper;
	private final ChongwuNeidanCategoryMapper chongwuNeidanCategoryMapper;

	@Autowired
	public ChongwuNeidanCategoryServiceImpl(
			UploadUtils uploadUtils,
			ImageUpdater imageUpdater,
			ChongwuCategoryMapper chongwuCategoryMapper,
			ChongwuNeidanCategoryMapper chongwuNeidanCategoryMapper) {
		this.uploadUtils = uploadUtils;
		this.imageUpdater = imageUpdater;
		this.chongwuCategoryMapper = chongwuCategoryMapper;
		this.chongwuNeidanCategoryMapper = chongwuNeidanCategoryMapper;
	}

	@Override
	public void download() throws IOException {
		List<ChongwuNeidanCategory> list = chongwuNeidanCategoryMapper.selectList(null);

		// 删除无效的图片
		list.removeIf(new Predicate<ChongwuNeidanCategory>() {
			@Override
			public boolean test(ChongwuNeidanCategory category) {
				return StringUtils.isEmpty(category.getImage());
			}
		});

		// 文件名中文乱码问题
		String downloadFilename = StringUtils.encode("宠物内丹图片.zip");

		// 设置响应头
		HttpServletResponse response = HttpUtils.getResponse();

		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);

		try (
				ServletOutputStream outputStream = response.getOutputStream();
				ZipOutputStream zos = new ZipOutputStream(outputStream);
		) {
			for (ChongwuNeidanCategory chongwuNeidanCategory : list) {
				String image = chongwuNeidanCategory.getImage();
				String fileName = chongwuNeidanCategory.getName() + StringUtils.getFileType(image);

				ZipEntry zipEntry = new ZipEntry(fileName);

				zos.putNextEntry(zipEntry);

				URL url = new URL("file", "localhost", uploadUtils.getRoot() + image);
				InputStream inputStream = url.openConnection().getInputStream();

				byte[] bytes = new byte[1024];
				int len;

				while ((len = inputStream.read(bytes)) != -1) {
					zos.write(bytes, 0, len);
				}

				inputStream.close();
			}
		}
	}

	@Override
	public String upload(MultipartFile file) throws IOException {
		String directory = CustomDirectories.DIRECTORY_CWND;

		return uploadUtils.upload(file, directory);
	}

	@Override
	public void insert(ChongwuNeidanCategoryDTO chongwuNeidanCategoryDTO) {
		chongwuNeidanCategoryDTO.setId(null);

		boolean result = validateDuplicate(chongwuNeidanCategoryDTO);

		if (result) {
			ChongwuNeidanCategory chongwuNeidanCategory = toEntity(chongwuNeidanCategoryDTO);

			chongwuNeidanCategory.setId(null);

			chongwuNeidanCategoryMapper.insert(chongwuNeidanCategory);
		}
	}

	@Override
	public void updateById(ChongwuNeidanCategoryDTO chongwuNeidanCategoryDTO) {
		if (chongwuNeidanCategoryDTO.getId() == null) {
			throw new GlobalException(ResponseCode.BAD_REQUEST, "宠物内丹类型ID不能为空。");
		}

		boolean result = validateDuplicate(chongwuNeidanCategoryDTO);

		if (result) {
			ChongwuNeidanCategory chongwuNeidanCategory = toEntity(chongwuNeidanCategoryDTO);

			chongwuNeidanCategoryMapper.updateById(chongwuNeidanCategory);
		}
	}

	@Override
	public void updateImageById(Integer id, String image) {
		imageUpdater.updateImageById(image, new Consumer<Object>() {
			@Override
			public void accept(Object o) {
				UpdateWrapper<ChongwuNeidanCategory> updateWrapper = WrapperUtils.getUpdateWrapper(id, image);

				chongwuNeidanCategoryMapper.update(updateWrapper.getEntity(), updateWrapper);
			}
		});
	}

	@Override
	public List<ChongwuNeidanCategory> selectAll() {
		QueryWrapper<ChongwuNeidanCategory> queryWrapper = new QueryWrapper<>();

		queryWrapper.orderByAsc("type");

		return chongwuNeidanCategoryMapper.selectList(queryWrapper);
	}

	@Override
	public ChongwuNeidanCategory selectById(Integer id) {
		return chongwuNeidanCategoryMapper.selectById(id);
	}

	@Override
	public ChongwuNeidanCategory selectByChongwuId(Integer chongwuId) {
		ChongwuCategory chongwuCategory = chongwuCategoryMapper.selectById(chongwuId);

		return chongwuNeidanCategoryMapper.selectById(chongwuCategory.getNeidanId());
	}

	@Override
	public Page<ChongwuNeidanCategory> selectByPage(ChongwuNeidanCategoryPager pager) {
		QueryWrapper<ChongwuNeidanCategory> queryWrapper = new QueryWrapper<>();
		Page<ChongwuNeidanCategory> page = Pager.ofPage(pager);

		queryWrapper.like(
				StringUtils.isNotEmpty(pager.getName()),
				"name", pager.getName()
		);
		queryWrapper.eq(
				pager.getType() != null,
				"type", pager.getType()
		);

		return chongwuNeidanCategoryMapper.selectPage(page, queryWrapper);
	}

	@Override
	public List<ChongwuNeidanCategory> selectList(Integer type, Integer chongwuId) {
		if (chongwuId != null && NeidanTypes.ZSND.getValue().equals(type)) {
			// 通过ID查询宠物类型
			ChongwuCategory chongwuCategory = chongwuCategoryMapper.selectById(chongwuId);

			// 通过ID查询宠物内丹类型
			QueryWrapper<ChongwuNeidanCategory> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("id", chongwuCategory.getNeidanId());

			return chongwuNeidanCategoryMapper.selectList(queryWrapper);
		} else {
			QueryWrapper<ChongwuNeidanCategory> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("id", 0);
			queryWrapper.or();
			queryWrapper.eq(
					type != null,
					"type", type
			);

			return chongwuNeidanCategoryMapper.selectList(queryWrapper);
		}
	}

	/**
	 * 验证内丹名称是否重复
	 * @param chongwuNeidanCategoryDTO ChongwuNeidanCategoryDTO
	 * @return 内丹名字已经存在，返回false；否则返回true
	 */
	private boolean validateDuplicate(ChongwuNeidanCategoryDTO chongwuNeidanCategoryDTO) {
		Integer id = chongwuNeidanCategoryDTO.getId();
		String name = chongwuNeidanCategoryDTO.getName();

		QueryWrapper<ChongwuNeidanCategory> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("name", name);
		queryWrapper.ne(id != null, "id", id);

		Long count = chongwuNeidanCategoryMapper.selectCount(queryWrapper);

		if (count > 0) {
			throw new GlobalException(ResponseCode.FORBIDDEN, "内丹名称重复。");
		}

		return true;
	}

	private ChongwuNeidanCategory toEntity(ChongwuNeidanCategoryDTO chongwuNeidanCategoryDTO) {
		ChongwuNeidanCategory chongwuNeidanCategory = new ChongwuNeidanCategory();

		chongwuNeidanCategory.setId(chongwuNeidanCategoryDTO.getId());
		chongwuNeidanCategory.setName(chongwuNeidanCategoryDTO.getName());
		chongwuNeidanCategory.setType(chongwuNeidanCategoryDTO.getType());
		chongwuNeidanCategory.setNote(chongwuNeidanCategoryDTO.getNote());
		chongwuNeidanCategory.setTemplate(chongwuNeidanCategoryDTO.getTemplate());

		return chongwuNeidanCategory;
	}

}